The main goal of native compilation of virtual machine code is to boost performance of programs written in a computer language that is implemented on a virtual machine. A virtual machine is an abstract computing machine that is simulated on a real computing machine, and, like a real computing machine, a virtual machine has an instruction set and manipulates various memory areas at run time. Currently, the JAVA programming language is one of the most popular programming languages that are implemented on a virtual machine; other examples include the SMALLTALK-80 programming language and the UCSD Pascal programming language.
Programming languages that are implemented on a virtual machine have many advantages over programming languages that are compiled into native code, which is executed directly by a particular hardware platform. Because the virtual machine is abstract and capable of simulation on a variety of different computing platforms, virtual machine code is highly portable and can be run on the different computing platforms without modification, simply by interpreting the virtual machine code instructions one at a time. The portability advantage of virtual machine code, however, comes at a cost, because interpretation of virtual machine code is typically much slower than directly executing equivalent native code. Accordingly, there has been much interest in compiling virtual machine code into native code and executing that native code to boost performance.
One approach to native compilation is known as “just-in-time” compilation, in which native code is generated only until when the virtual machine code is about to be executed at run-time. Just-in-time compilation can profitably be used by identifying performance-critical spots and compiling these critical code fragments. Because compilation overhead in just-in-time compilation contributes to the combined run-time execution cost, just-in-time compilers must carefully limit the scope of the code that is subject to compilation. For example, just-in-time compilers typically limit the scope of their analysis to one Java method or other kind of routine at a time. This restriction, however, limits the opportunities for some of the most important code optimizations, which require inter-procedural code inspection. Another disadvantage of just-in-time compilation occurs in the context of server-side execution. Just-in-time compilation adversely affects scalability unless the dynamically generated native code can be shared among independent user sessions, which is a difficult problem to solve.
Unlike just-in-time compilation, “ahead-of-time” compilation does not consume critical run-time resources, because the virtual machine code is compiled well before the program is invoked by a user. Ahead-of-time compilers are able to do inter-procedural optimization analysis, in which the entire application is analyzed to identify code optimizations. In server-side execution environments, ahead-of-time compilation is an attractive option because the resulting native code can be shared among different users, thereby improving scalability.
Accordingly, ahead of time compilers are increasingly being used as a way to deploy complete, frozen Java solutions, achieving high performance by applying various code optimizations. Most such tools are “monolithic” compilers, which assume that the transitive closure of the compiled classes is determined and fixed at compile time. Thus, these monolithic compilers cannot interact with the Java interpreter and, in fact, break the semantics of the Java virtual machine. For example, most monolithic compilers derive their high performance from freezing layouts of Java instances and virtual tables. However, freezing instance and virtual table layouts violates Java virtual machine semantics, because updates to Java classes on the virtual machine are not reflected in the frozen, monolithically compiled application.
Therefore, there is a need for a native compilation technology that does not incur the run-time execution costs of just-in-time compilers while avoiding the violation of virtual machine semantics suffered by ahead-of-time monolithic compilers.